# -*- coding: utf-8 -*-
import random
import subprocess
import time
import logging
import argparse
from datetime import datetime
import requests
import base64
from io import BytesIO
from appium import webdriver
# from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
logger = logging.getLogger()

APP = "WB"

app_package_map = {
    "WB": ("com.sina.weibo", ".VisitorMainTabActivity")
}


class WBAppiumOperate:
    def __init__(self, **kwargs):
        # 用于记录已评论的内容
        self.used_comments = []
        self.screen_width = None
        self.screen_height = None
        self.text = kwargs.get("text").replace("\\n", "\n")
        self.targetUrlList = kwargs.get("targetUrlList").replace("\\n", "\n")
        self.deviceName = kwargs.get("deviceName")
        self.appium_url = kwargs.get("appium_url")
        self.platformVersion = kwargs.get("platformVersion")
        self.systemPort = kwargs.get("systemPort")
        self.adbPort = kwargs.get("adbPort")
        self.job_id = kwargs.get("job_id")

        self.driver = None
        self.max_retries = 1
        self.failure_count = 0

    def upload_screenshot(self, fileName):
        """
        将当前屏幕截图上传至指定接口
        :param job_id: rpaTaskid，即任务ID
        """
        try:
            # 1. 获取截图的 Base64 字符串
            screenshot_base64 = self.driver.get_screenshot_as_base64()

            if not screenshot_base64:
                logger.error("截图失败，无法获取 Base64 数据")
                return False

            # 2. 构造文件数据（模拟 multipart/form-data）
            # 使用指定的文件名格式
            files = {
                'files': [
                    {
                        "file": screenshot_base64,
                        "fileName": f"{fileName}"
                    }
                ]
            }

            # 3. 发送 POST 请求
            url = f"http://172.25.1.30:8889/social/device/task/upload/{self.job_id}"

            response = requests.post(url, json=files)

            if response.status_code == 200:
                logger.info(f"截图上传成功: {response.json()}")
            else:
                logger.error(f"截图上传失败，状态码: {response.status_code}, 响应: {response.text}")

        except Exception as e:
            logger.error(f"上传截图时发生异常: {e}")

    def run(self):
        while self.max_retries > 0:
            try:
                if self.driver:
                    self.driver.quit()
                self.connection()
                logger.info(f"设备 {self.deviceName} 连接成功")
                time.sleep(3)

                logger.info("开始执行微博评论任务...")
                self.script()
                break
            except Exception as e:
                logger.error(f"发生异常: {e}")
                self.failure_count += 1
                self.max_retries -= 1
                if self.max_retries == 0:
                    self.normal_end()
                    raise Exception("任务失败")
        logger.info("任务结束")

    @staticmethod
    def execute_adb_command(adb_command):
        """执行单条 ADB 命令"""
        try:
            logger.info(f"执行ADB命令: {adb_command}")
            result = subprocess.run(
                adb_command,
                shell=True,
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            logger.info(f"命令执行成功: {adb_command}")
            return result.stdout.decode('utf-8')
        except subprocess.CalledProcessError as e:
            logger.error(f"命令执行失败: {adb_command}")
            logger.error(f"错误信息: {e.stderr.decode('utf-8')}")

    def initialize_device_settings(self):
        """执行设备初始化所需的 ADB 命令"""
        logger.info("开始初始化设备设置")

        commands = [
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global adb_keep_usb_enabled 1",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global miui_optimization 0",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global tcp_keepalive 1",
            f"adb -s {self.deviceName} -P {self.adbPort} shell dumpsys battery unplug",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm enable io.appium.uiautomator2.server",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm enable io.appium.uiautomator2.server.test",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global background_process_limit 5",
            f"adb -s {self.deviceName} -P {self.adbPort} shell am set-standby-bucket io.appium.uiautomator2.server ACTIVE",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm trim-caches 500M",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm clear io.appium.uiautomator2.server",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm clear io.appium.uiautomator2.server.test",
            f"adb -s {self.deviceName} -P {self.adbPort} shell input keyevent KEYCODE_CLEAR"

            f"adb -s {self.deviceName} -P {self.adbPort} shell pm grant com.sina.weibo android.permission.READ_EXTERNAL_STORAGE"
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm grant com.sina.weibo android.permission.WRITE_EXTERNAL_STORAGE"
        ]

        for cmd in commands:
            try:
                self.execute_adb_command(cmd)
            except Exception as e:
                logger.error(f"执行命令失败: {cmd}")
                logger.error(f"错误详情: {e}")

    def connection(self):
        """建立Appium连接"""
        self.initialize_device_settings()
        desired_caps = {
            "platformName": "Android",
            "platformVersion": self.platformVersion,
            "deviceName": self.deviceName,
            "udid": self.deviceName,
            "automationName": "UiAutomator2",
            "appPackage": app_package_map[APP][0],
            "appActivity": app_package_map[APP][1],
            "noReset": True,
            "fullReset": False,
            "systemPort": int(self.systemPort),
            "adbPort": int(self.adbPort),
            "appWaitForLaunch": True,
            "noSign": True,
            "autoLaunch": True,
            "newCommandTimeout": 180,
            "skipLogcatCapture": True,
            "disableWindowAnimation": True,
            "disableAndroidWatchers": True,
            "adbExecTimeout": 30000,
            "uiautomator2ServerInstallTimeout": 60000,
            "skipDeviceInitialization": True,

        }
        self.driver = webdriver.Remote(self.appium_url, desired_caps)
        # self.driver = webdriver.Remote(self.appium_url, options=UiAutomator2Options().load_capabilities(desired_caps))
        self.screen_width, self.screen_height = self.get_window_size()

    def script(self):
        # 按行分割 targetUrlList
        url_lines = self.targetUrlList.split('\n')
        target_urls = []
        # 提取所有有效的链接
        for line in url_lines:
            line = line.strip()
            if line:  # 忽略空行
                extracted_url = line
                if extracted_url:  # 只添加非空链接
                    target_urls.append(extracted_url)

        if not target_urls:
            logger.error("未找到有效的链接")
            return

        logger.info(f"共找到 {len(target_urls)} 个有效链接")

        # 随机选择一个评论
        selected_comment = self.get_comment_text()
        logger.info(f"准备评论内容：{selected_comment}")

        # 处理每个链接，包含重试机制
        for i, target_url in enumerate(target_urls):
            logger.info(f"开始处理第 {i + 1}/{len(target_urls)} 个链接: {target_url}")
            retry_count = 0
            max_retry_per_url = 2

            while retry_count <= max_retry_per_url:
                try:
                    # 执行单个链接的处理流程
                    self.process_single_url(target_url, selected_comment)
                    logger.info(f"链接 {target_url} 处理成功")
                    break  # 成功处理后跳出重试循环

                except Exception as e:
                    retry_count += 1
                    if retry_count <= max_retry_per_url:
                        logger.warning(f"链接 {target_url} 处理失败，第 {retry_count} 次重试: {e}")
                        time.sleep(3)  # 等待3秒后重试
                    else:
                        logger.error(f"链接 {target_url} 处理失败，已达到最大重试次数 ({max_retry_per_url}): {e}")
                        raise e
        self.normal_end()
        logger.info("所有链接处理完成")

    def process_single_url(self, target_url, selected_comment):

        self.open_weibo_link(target_url)
        time.sleep(5)  # 等待页面加载
        self.leave_comment(selected_comment)
        time.sleep(5)

    def open_weibo_link(self, url):
        """使用微博打开指定链接"""
        logger.info(f"打开链接: {url}")
        mblogid = url.split("/")[-1]
        weibo_scheme_url = f"sinaweibo://detail?mblogid={mblogid}"
        # component ="com.sina.weibo/com.sina.weibo.feed.DetailWeiboActivity"
        try:
            subprocess.run([
                'adb', '-s', self.deviceName, '-P', self.adbPort,
                'shell', 'am', 'start',
                '-a', 'android.intent.action.VIEW',
                '-c', 'android.intent.category.DEFAULT',
                # '-n', component,  # 明确指定 Component
                '-d', weibo_scheme_url
            ], check=True, capture_output=True, text=True)
            logger.info("链接打开成功")
        except Exception as e:
            logger.error(f"打开链接失败: {e}")
            raise

    def leave_comment(self, selected_comment):
        """进入评论区并启动处理逻辑"""
        try:
            logger.info("进入微博页面")
            # 添加滑动开始日志
            logger.info("开始滑动")
            self.swipe_to_next()
            time.sleep(2)
            self.swipe_to_next()

            bottom_container = self.find_element_with_retry(AppiumBy.XPATH,
                                                            '//android.widget.RelativeLayout[@resource-id="com.sina.weibo:id/rl_topContainer"]/android.widget.LinearLayout[2]')

            try:
                like_button = bottom_container.find_element(AppiumBy.XPATH,
                                                            '(//android.widget.LinearLayout[@resource-id="com.sina.weibo:id/lyButton"])[3]')
            except Exception as e:
                like_button = bottom_container.find_element(AppiumBy.XPATH,
                                                            '//android.widget.LinearLayout[@resource-id="com.sina.weibo:id/detail_operation_bottom_bar"]/android.widget.FrameLayout/android.view.ViewGroup/android.view.ViewGroup/android.widget.LinearLayout[3]')
            if like_button:
                like_button.click()
                logger.info("点赞成功")

            try:
                commit_button = bottom_container.find_element(AppiumBy.XPATH,
                                                              '(//android.widget.LinearLayout[@resource-id="com.sina.weibo:id/lyButton"])[2]')
                logger.info("找到视频评论框:")
            except Exception as e:
                try:
                    logger.info("找不到视频评论框，尝试找到:", e)
                    commit_button = bottom_container.find_element(AppiumBy.XPATH,
                                                                  '//android.widget.LinearLayout[@resource-id="com.sina.weibo:id/detail_operation_bottom_bar"]/android.widget.FrameLayout/android.view.ViewGroup/android.view.ViewGroup/android.widget.LinearLayout[2]')
                    logger.info("找到图文评论框:")
                except Exception as e:
                    raise e

            # '(//android.widget.LinearLayout[@resource-id="com.sina.weibo:id/lyButton"])[2]'
            #
            # commit_button = self.find_element_with_retry(AppiumBy.XPATH,
            #                                              '//android.widget.LinearLayout[@resource-id="com.sina.weibo:id/detail_operation_bottom_bar"]/android.widget.FrameLayout/android.view.ViewGroup/android.view.ViewGroup/android.widget.LinearLayout[2]')
            if commit_button:
                commit_button.click()
                logger.info("成功点击评论框")

            time.sleep(2)

            commit_edit = self.find_element_with_retry(AppiumBy.XPATH,
                                                       '//android.widget.EditText[@resource-id="com.sina.weibo:id/edit_view"]')
            commit_edit.send_keys(selected_comment)
            time.sleep(2)

            submit_button = self.find_element_with_retry(AppiumBy.XPATH,
                                                         '//android.widget.TextView[@resource-id="com.sina.weibo:id/tv_send"] | '
                                                         '//android.widget.TextView[@resource-id="com.sina.weibo:id/btnSend"]')
            submit_button.click()
            time.sleep(2)

            self.upload_screenshot(fileName=f"评论_{selected_comment}")

            logger.info("评论完成")
        except Exception as e:
            logger.error(f"评论失败: {e}")
            raise e

    def get_comment_text(self):
        """
        获取评论文本，根据最大重复次数设置决定是否允许重复
        """
        available_texts = [t for t in self.text.split('\n') if
                           self.used_comments.count(t) >= 1]

        if not available_texts:
            # 如果所有文本都已达到最大重复次数，则重置已使用列表
            self.used_comments.clear()
            available_texts = self.text.split('\n')

        comment_text = random.choice(available_texts)

        # 如果设置了最大重复次数，则记录已使用的评论
        self.used_comments.append(comment_text)

        logger.info(f"选择评论文本: {comment_text}, 该文本已使用次数: {self.used_comments.count(comment_text)}")

        return comment_text

    def find_element_with_retry(self, by, value, timeout=10):
        """带重试的元素定位"""
        retry_num = 3
        for attempt in range(retry_num):
            try:
                element = WebDriverWait(self.driver, timeout).until(
                    EC.presence_of_element_located((by, value))
                )
                return element
            except Exception as e:
                if attempt < 2:
                    logger.warning(f"定位元素重试 ({attempt + 1}/3): {value}")
                    time.sleep(2)
                elif attempt == 2:
                    logger.error(f"元素定位失败: {value}")
                    logger.error(f"{e}")
                    raise e

    def swipe_to_next(self):
        # 向上滑动
        self.driver.swipe(
            self.screen_width / 2,
            self.screen_height * 0.8,
            self.screen_width / 2,
            self.screen_height * 0.2,
            200
        )

    def get_window_size(self):
        size = self.driver.get_window_size()
        return size['width'], size['height']

    def normal_end(self):
        logger.info("返回首页并退出")
        try:
            self.driver.press_keycode(3)  # HOME 键
            self.driver.quit()
        except:
            pass

    def scroll_to_comment_element(self):
        """
        滑动直到出现评论元素
        """
        # 定义评论元素的XPath
        comment_xpath = '//android.widget.TextView[@resource-id="com.sina.weiboid/ty_comment_count"]'
        
        # 设置最大滑动次数
        max_swipe_times = 10
        swipe_count = 0
        
        while swipe_count < max_swipe_times:
            try:
                # 尝试查找评论元素
                comment_element = self.find_element_with_retry(AppiumBy.XPATH, comment_xpath)
                if comment_element:
                    logger.info("已找到评论元素")
                    return True
                else:
                    # 如果没有找到，进行滑动
                    self.swipe_to_next()
                    swipe_count += 1
                    time.sleep(2)
            except Exception as e:
                logger.warning(f"查找评论元素时发生异常: {e}")
                swipe_count += 1
                time.sleep(2)
        
        logger.error("超过最大滑动次数仍未找到评论元素")
        return False

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-j', '--job_id', dest='job_id', type=str, default=None, required=True, help='target job_id')
    parser.add_argument('-u', '--appium_url', dest='appium_url', type=str, default=None, help='target appium_url')
    parser.add_argument('-d', '--deviceName', dest='deviceName', type=str, default=None, help='target deviceName')
    parser.add_argument('-s', '--systemPort', dest='systemPort', type=str, default=None, help='target systemPort')
    parser.add_argument('-a', '--adbPort', dest='adbPort', type=str, default=None, help='target adbPort')
    parser.add_argument('-p', '--platformName', dest='platformName', type=str, default=None, help='target platformName')
    parser.add_argument('-ver', '--platformVersion', dest='platformVersion', type=str, default=None,
                        help='target platformVersion')
    parser.add_argument('-accountId', '--accountId', dest='accountId', type=str, default="000", help='target accountId')

    parser.add_argument('-v', '--variables', dest='variables', type=str, default='{}', help='target variables')
    parser.add_argument('-targetUrlList', '--targetUrlList', required=True)
    parser.add_argument('-text', '--text', required=True, default="私我\n看我的空间，分享给你")
    args = parser.parse_args()
    WBAppiumOperate(**vars(args)).run()
